package com.vercon.common.wifi

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.net.wifi.ScanResult
import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiManager
import android.os.Build
import androidx.core.app.ActivityCompat
import com.vercon.common.utils.LogUtils
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.annotations.NonNull
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit


/**
 * Created by YZC on 2019/6/26
 */
class EasyzcWifi private constructor() : EasyzcWifiStateListener {


    companion object {
        fun get() = Holder.INSTANCE
    }
    private val coroutineScope = CoroutineScope(Dispatchers.Default)
    private val TAG = javaClass.simpleName
    private var manager: WifiManager? = null
    private var connectivityManager: ConnectivityManager? = null
    private var wifiNetworkInfo: NetworkInfo? = null

    private val list = arrayListOf<ScanResult>()
    private var mScanResult: ScanResult? = null
    private var mWifiConfiguration: WifiConfiguration? = null
    private val receiver = EasyzcWifiReceiver()

    private val listeners = arrayListOf<EasyzcWifiStateListener?>()

    private object Holder {
        val INSTANCE = EasyzcWifi()
    }

    init {

    }

    fun register(context:Context) {
        manager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager?
        connectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
        wifiNetworkInfo = connectivityManager?.getNetworkInfo(ConnectivityManager.TYPE_WIFI)

        // 注册wifi广播
        context.applicationContext.registerReceiver(receiver,
            EasyzcWifiReceiver.filter()
        )
        enable = manager?.isWifiEnabled!!
    }

    fun unregister() {
        manager = null
        connectivityManager = null
        mDisposable?.let { it.dispose() }
    }

    private var mDisposable: Disposable? = null
    private val isLOLLIPOP = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
    private fun startTimer() {
        LogUtils.d(TAG, "EasyzcWifi开启定时")
        Observable.interval(30, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Observer<Long> {
                override fun onSubscribe(@NonNull disposable: Disposable) {
                    mDisposable = disposable
                }

                override fun onNext(t: Long) {
//                        LogUtils.d(TAG, "EasyzcWifi定时执行")
                    if (isLOLLIPOP) {
                        refresh()
                    } else {
                        manager?.startScan()
                    }
                }

                override fun onError(@NonNull e: Throwable) {
                    mDisposable?.let { it.dispose() }
                }

                override fun onComplete() {
                    mDisposable?.let { it.dispose() }
                }
            })
    }


    fun addListener(listener: EasyzcWifiStateListener) {
        listeners.add(listener)
        if (null == mDisposable || mDisposable?.isDisposed!!) {
            startTimer()
        }
        LogUtils.d(TAG, "addConnectStateListener ${listeners.size}")
    }


    fun removeListener(listener: EasyzcWifiStateListener) {
        listeners.remove(listener)
        if (listeners.size == 0 && mDisposable != null && !mDisposable?.isDisposed!!) {
            LogUtils.d(TAG, "EasyzcWifi取消定时")
            mDisposable?.dispose()
        }
        LogUtils.d(TAG, "removeConnectStateListener ${listeners.size}")
    }

    /**
     * 连接准备
     */
    fun preConnect(scanResult: ScanResult, block: () -> Unit) {
        mScanResult = null
        mWifiConfiguration = null
        var wifiConfiguration = isExsits(scanResult.SSID)
        // 无密码
        if (getSecurity(scanResult) == 0) {
            noPasswordConnect(scanResult.SSID)
            return
        }
        // 已经连接过 直接连接
        if (wifiConfiguration != null) {
            connect(wifiConfiguration)
            return
        }
        // 输入密码
        block.invoke()
    }

    /**
     * 点击连接wifi
     */
    fun connect(wifiConfiguration: WifiConfiguration?) {
        if (wifiConfiguration == null) return
        mWifiConfiguration = wifiConfiguration
        val tempConfig = isExsits(wifiConfiguration.SSID)
        // 重新配置网络
        if (tempConfig != null) {
           val removeNetwork = manager?.disableNetwork(wifiConfiguration.networkId)
            LogUtils.e(TAG, "removeNetwork=" + removeNetwork)
        }
        // 连接
        if (wifiConfiguration.networkId >= 0) { //已经连接的网络使用
            LogUtils.e(TAG, " manager?.enableNetwork")
            val enableNetwork = manager?.enableNetwork(wifiConfiguration.networkId, true)
            LogUtils.e(TAG, "enableNetwork=" + enableNetwork)
            manager?.updateNetwork(wifiConfiguration);
        }else {
            val i: Int? = manager?.addNetwork(wifiConfiguration)
            if (i!! > 0) {
                manager?.saveConfiguration()
                manager?.enableNetwork(i, true)
            }
        }
    }

    /**
     * 刷新wifi显示
     */
    @SuppressLint("NewApi")
    fun refresh() {
        coroutineScope.launch (Dispatchers.IO){
            try {
                enable = manager?.isWifiEnabled!!
                if (!enable) return@launch
                launch(Dispatchers.Main) {
                    listeners.forEach { it?.onScaning() }
                }
                val tmpList = manager?.scanResults!!
                var str = ""
                tmpList.forEach { str += it.SSID + ", " }
                LogUtils.d(TAG, "isConnected="+isConnected())
                if (isConnected()) {
                    val wifiInfo = manager?.connectionInfo
                    LogUtils.d(TAG, " $wifiInfo")
                    for (tmp in tmpList) {
                        if (isEquals(tmp.SSID,wifiInfo?.ssid!!) && wifiInfo?.bssid == tmp.BSSID) {
                            mScanResult = tmp
                            // 当前连接的scanResult
                            listeners.forEach { listener ->
                                launch(Dispatchers.Main) {
                                    mScanResult?.let { listener?.onConnectSuccess(it) }
                                }
                            }
                            LogUtils.e("找到已连接网络")
                            list.add(tmp)
                        }
                    }
                }
                // 从wifi列表中删除已经连接的wifi
                for (tmp in list) tmpList.remove(tmp)
                if (list != null && list.size == 0){
                    val wifiInfo = manager?.connectionInfo
                    val aa = ScanResult()
                    aa.SSID= wifiInfo!!.ssid
                    listeners.forEach { listener ->
                        launch (Dispatchers.Main) {
                            aa?.let { listener?.onConnectSuccess(it) }
                        }
                    }
                    LogUtils.e("使用新方式的连接网络="+wifiInfo!!.ssid)
                }

                list.clear()
                list.addAll(tmpList)
                // 排序
                var level1: Int
                var level2: Int
                list.sortWith(kotlin.Comparator { o1, o2 ->
                    var isSave = isSave(o1.SSID) == isSave(o2.SSID)
                    if (!isSave) {
                        if (isSave(o2.SSID)) 2 else -2
                    } else {
                        level1 = WifiManager.calculateSignalLevel(o1.level, 100)
                        level2 = WifiManager.calculateSignalLevel(o2.level, 100)
                        if (level2 > level1) {
                            1
                        } else if (level2 < level1) {
                            -1
                        } else {
                            0
                        }
//                        if (level2 ==  level1) 0
//                        if (level2 - level1 > 0) 1 else -1
                    }

                })
                launch(Dispatchers.Main) {
                    listeners.forEach { it?.onScanResult(list) }
                }
            } catch (e: Exception) {
            }
        }

    }

    /**
     * 开关
     */
    @Volatile
    var enable: Boolean = false

    fun getWifiEnable(): Boolean = manager?.isWifiEnabled!!

    fun on(): Boolean = manager?.setWifiEnabled(true)!!

    fun off(): Boolean = manager?.setWifiEnabled(false)!!

    fun turn(block: (Boolean) -> Unit) {
        enable = !enable
        LogUtils.d(TAG, " enable $enable")
        block.invoke(enable)
        manager?.setWifiEnabled(enable)!!

    }

    fun turn(block: Boolean) {
        enable = !enable
        LogUtils.d(TAG, " enable $enable")
        manager?.setWifiEnabled(enable)!!

    }

    /**
     * ==============================广播状态回调===================================================
     */
    override fun onScanResult(list: List<ScanResult>) {
        LogUtils.d(TAG, "onScanResult ")
    }

    override fun onNetWorkStateChanged() {
        LogUtils.d(TAG, "onNetWorkStateChanged ")
        refresh()
    }

    override fun onWiFiStateChanged() {
        LogUtils.d(TAG, "onWiFiStateChanged ")
    }

    override fun onConnectFault() {
        LogUtils.d(TAG, "onConnectFault ")
        listeners.forEach { it?.onConnectFault() }
        // 密码错误
        LogUtils.d(TAG, "onConnectFault 忘记密码 $mWifiConfiguration")
        val ssid = mWifiConfiguration?.SSID
        for (configuredNetwork in manager?.configuredNetworks!!) {
            if (ssid == configuredNetwork.SSID) {
                manager?.removeNetwork(configuredNetwork.networkId)
                break
            }
        }
    }

    override fun onConnectSuccess(scanResult: ScanResult?) {
        LogUtils.d(TAG, "onConnectSuccess11 ")
//        EventBus.getDefault().post(HasNetEvent())
        listeners.forEach { listener ->
            mScanResult?.let { listener?.onConnectSuccess(it) }
        }
    }
    override fun onDisconnected() {
        listeners.forEach { it?.onDisconnected() }
    }
    override fun onConnecting() {
        listeners.forEach { it?.onConnecting() }
    }

    override fun onScaning() {

    }


    /**
     * ==============================帮助方法===================================================
     */

    /**
     * 得到当前连接的WiFi  SSID
     */
    fun getConnectedSSID(): String {
        var ssid: String? = manager?.connectionInfo?.ssid
        if (ssid?.substring(0, 1) == "\"" && ssid.substring(ssid.length - 1) == "\"") {
            ssid = ssid.substring(1, ssid.length - 1)
        }
        return ssid!!
    }

    /**
     * 是否处于wifi连接的状态
     */
    fun isConnected(): Boolean {
        return wifiNetworkInfo!!.isConnected || wifiNetworkInfo?.isAvailable!!
    }

    /**
     * 判断是否有密码.
     */
    val WIFI_NO_PASS = 0
    private val WIFI_WEP = 1
    private val WIFI_PSK = 2
    private val WIFI_EAP = 3
    fun getSecurity(result: ScanResult?): Int {
        if (result?.capabilities != null) {
            when {
                result.capabilities.contains("WEP") -> return WIFI_WEP
                result.capabilities.contains("PSK") -> return WIFI_PSK
                result.capabilities.contains("EAP") -> return WIFI_EAP
            }
        }
        return WIFI_NO_PASS
    }

    /**
     * 连接没有密码wifi.
     */
    fun noPasswordConnect(ssid: String) {
        val configuration = WifiConfiguration()
        configuration.SSID = "\"" + ssid + "\""
        configuration.allowedAuthAlgorithms.clear()
        configuration.allowedGroupCiphers.clear()
        configuration.allowedKeyManagement.clear()
        configuration.allowedPairwiseCiphers.clear()
        configuration.allowedProtocols.clear()
        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
        connect(configuration)
    }

    /**
     * 连接有密码的wifi.
     * @param SSID     ssid
     * @param Password Password
     * @return apConfig
     */
    fun passwordConnect(SSID: String, Password: String) {
        val apConfig = WifiConfiguration()
        apConfig.SSID = "\"" + SSID + "\""
        apConfig.preSharedKey = "\"" + Password + "\""
        //不广播其SSID的网络
        apConfig.hiddenSSID = true
        apConfig.status = WifiConfiguration.Status.ENABLED
        //公认的IEEE 802.11验证算法。
        apConfig.allowedAuthAlgorithms.clear()
        apConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)
        //公认的的公共组密码
        apConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP)
        apConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)
        //公认的密钥管理方案
        apConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
        //密码为WPA。
        apConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)
        apConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
        //公认的安全协议。
        apConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN)
        connect(apConfig)
    }

    /**
     * 以前是否连接过
     */
    private fun isExsits(SSID: String): WifiConfiguration? {
        val existingConfigs = manager?.configuredNetworks
        for (existingConfig in existingConfigs!!) {
            if (existingConfig.SSID == "\"" + SSID + "\"" || existingConfig.SSID ==SSID) {
                return existingConfig
            }
        }
        return null
    }
    /**
     * 是否相等
     */
    private fun isEquals(SSID: String,SSID_connect:String): Boolean {
        if (SSID_connect == "\"" + SSID + "\"" || SSID_connect ==  SSID) {
            return true
        }
        return false
    }
    private fun isSave(SSID: String): Boolean {
        val existingConfigs = manager?.configuredNetworks
        if (existingConfigs != null) {
            for (existingConfig in existingConfigs!!) {
                if (existingConfig.SSID == "\"" + SSID + "\"") {
                    return true
                }
            }
        }
        return false
    }

    //取消保存WiFi
    fun removeWifi(context: Context, result: ScanResult): Boolean {
        if (getNetworkId(context, result.SSID) != -1) {
            manager?.removeNetwork(getNetworkId(context, result.SSID))
            manager?.saveConfiguration()
            return true
        }
        return false
    }

    //获取WiFiid
    private fun getNetworkId(context: Context, wifiSSID: String): Int {
        if (ActivityCompat.checkSelfPermission(
                        context,
                        Manifest.permission.ACCESS_FINE_LOCATION
                ) != PackageManager.PERMISSION_GRANTED
        ) {
            return -1
        }
        val wifiConfigurationList = manager?.configuredNetworks
        if (wifiConfigurationList != null && wifiConfigurationList.size != 0) {
            for (i in wifiConfigurationList.indices) {
                val wifiConfiguration = wifiConfigurationList[i]
                // wifiSSID就是SSID
                if (wifiConfiguration.SSID != null && wifiConfiguration.SSID == "\"" + wifiSSID + "\"") {
                    LogUtils.d(" " + wifiConfiguration.networkId)
                    return wifiConfiguration.networkId
                } else {
                    LogUtils.d("-1 中上 " + wifiConfiguration.SSID + "  " + wifiSSID)
                }
            }
        }

        return -1
    }

    /**
     * 返回item在list中的坐标
     */
    fun getItemPosition(list: List<ScanResult>, item: ScanResult): Int {
        for (i in list.indices) {
            if (item.SSID == list[i].SSID) {
                return i
            }
        }
        return -1
    }


}